<?php
/**
 * SimplifyPHP Framework
 *
 * This file is part of SimplifyPHP Framework.
 *
 * SimplifyPHP Framework is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * SimplifyPHP Framework is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * @author Rodrigo Rutkoski Rodrigues, <rutkoski@gmail.com>
 */

require_once (SY_DIR.'/lib/pomo/mo.php');

/**
 * L10N.
 *
 * @author Rodrigo Rutkoski Rodrigues, <rutkoski@gmail.com>
 * @package Simplify_Kernel
 */
class Language
{

  /**
   * 
   * @var Config
   */
  public static $config;

  /**
   * 
   * @var string
   */
  private static $default_domain = 'default';

  /**
   * 
   * @var string
   */
  private static $locale;

  /**
   * 
   * @var array
   */
  private static $text_domains;

  /**
   * 
   * @param string $domain
   * @param string $path
   * @return array
   */
  public static function getAvailableLocales($domain = 'default', $path = null)
  {
    if (empty($path))
      $path = self::$config->get('locale_dir');
    
    $it = new DirectoryIterator($path);
    
    $locales = array(
      '' => 'Default' 
    );
    
    while ($it->valid()) {
      if (! $it->isDir() && ! $it->isDot() && preg_match('/^' . $domain . '_(.+?)\.mo$/', $it->getFilename(), $o)) {
        $locales[$o[1]] = Inflector::humanize($o[1]);
      }
      
      $it->next();
    }
    
    return $locales;
  }

  /**
   * Load a language file for a given $domain and $locale.
   * 
   * @param string $domain the name of the text domain
   * @param string $locale the locale
   * @param string $path language file path
   * @param string $codeset the codeset for the language file
   * @return void
   */
  public static function loadLanguageFile($domain = 'default', $locale = null, $path = null, $codeset = null)
  {
    if (empty($path))
      $path = self::$config->get('locale_dir');
    if (empty($locale))
      $locale = self::$config->get('locale');
    if (empty($codeset))
      $codeset = self::$config->get('codeset');
    
    $file = sy_fix_path($path . '/' . $domain . '_' . $locale . '.mo');
    
    if (file_exists($file)) {
      $mo = new MO();
      $mo->import_from_file($file);
      
      if (isset(self::$text_domains[$domain . '_' . $locale]->l10n)) {
        $mo->merge_with(self::$text_domains[$domain . '_' . $locale]->l10n);
      }
    }
    else {
      $mo = new NOOP_Translations();
    }
    
    self::$text_domains[$domain . '_' . $locale]->l10n = $mo;
    self::$text_domains[$domain . '_' . $locale]->codeset = $codeset;
  }

  /**
   * Set current locale.
   * 
   * @param string $locale the locale
   * @return void
   */
  public static function setLocale($locale = null)
  {
    self::$locale = $locale;
    setlocale(6, $locale);
  }

  /**
   * Set current text domain.
   * 
   * @param string $domain the text domain
   * @return void
   */
  public static function setTextDomain($domain = 'default')
  {
    self::$default_domain = $domain;
  }

  /**
   * Utility function to get a StreamReader for the given text domain.
   */
  function get_reader($domain = null, $locale = null)
  {
    if (empty($domain))
      $domain = self::$default_domain;
    
    if (empty($locale))
      $locale = self::$locale;
    
    if (! isset(self::$text_domains[$domain . '_' . $locale]->l10n)) {
      self::loadLanguageFile($domain, $locale);
    }
    
    return self::$text_domains[$domain . '_' . $locale]->l10n;
  }

  /**
   * Get the codeset for the given domain.
   */
  function get_codeset($domain = null)
  {
    if (! isset($domain))
      $domain = self::$default_domain;
    
    $locale = self::$locale;
    
    return (isset(self::$text_domains[$domain . '_' . $locale]->codeset)) ? self::$text_domains[$domain . '_' . $locale]->codeset : ini_get('mbstring.internal_encoding');
  }

  /**
   * Convert the given string to the encoding set by bind_textdomain_codeset.
   */
  function encode($text)
  {
    $source_encoding = mb_detect_encoding($text);
    $target_encoding = self::get_codeset();
    
    if ($source_encoding != $target_encoding) {
      return mb_convert_encoding($text, $target_encoding, $source_encoding);
    }
    else {
      return $text;
    }
  }

  /**
   * Lookup a message in the current domain.
   */
  function gettext($msgid)
  {
    $l10n = self::get_reader();
    return self::encode($l10n->translate($msgid));
  }

  /**
   * Plural version of gettext.
   */
  function ngettext($single, $plural, $number)
  {
    $l10n = self::get_reader();
    return self::encode($l10n->ngettext($single, $plural, $number));
  }

  /**
   * Override the current domain.
   */
  function dgettext($domain, $msgid)
  {
    $l10n = self::get_reader($domain);
    return self::encode($l10n->translate($msgid));
  }

  /**
   * Plural version of dgettext.
   */
  function dngettext($domain, $single, $plural, $number)
  {
    $l10n = self::get_reader($domain);
    return self::encode($l10n->ngettext($single, $plural, $number));
  }

  /**
   * Overrides the domain and category for a single lookup.
   */
  function dcgettext($domain, $msgid, $category)
  {
    $l10n = self::get_reader($domain, $category);
    return self::encode($l10n->translate($msgid));
  }

  /**
   * Plural version of dcgettext.
   */
  function dcngettext($domain, $single, $plural, $number, $category)
  {
    $l10n = self::get_reader($domain, $category);
    return self::encode($l10n->ngettext($single, $plural, $number));
  }

}

?>